local ByteArray = require("framework.cc.utils.ByteArray");
local SocketTCP = require("framework.cc.net.init").SocketTCP;
require("framework.cc.utils.bit")--bit是个全局的
local scnet = {};
function scnet.init()
    print("socket time:" .. SocketTCP.getTime());
    print("os time:" .. os.time());
    local socket = SocketTCP.new();
    socket:setName("GameTcp");
    --socket:setTickTime(1);
    --socket:setReconnTime(6);
    --socket:setConnFailTime(4);
    socket:addEventListener(SocketTCP.EVENT_DATA, scnet.tcpReceive);
    socket:addEventListener(SocketTCP.EVENT_CLOSE, scnet.tcpClose);
    socket:addEventListener(SocketTCP.EVENT_CLOSED, scnet.tcpClosed);
    socket:addEventListener(SocketTCP.EVENT_CONNECTED, scnet.tcpConnected);
    socket:addEventListener(SocketTCP.EVENT_CONNECT_FAILURE, scnet.tcpError);
    scnet.socket = socket;
    print("version is "..SocketTCP._VERSION);
    SocketTCP._DEBUG = true;
end

function scnet.connect(host, port, retryConnectWhenFailure)
    scnet.socket:connect(host, port, retryConnectWhenFailure);
end

-- 接收数据
function scnet.tcpReceive( event )
    local ba = ByteArray.new(ByteArray.ENDIAN_BIG);
    ba:writeBuf(event.data);
    ba:setPos(1);
    -- 注意有可能出现连包情况
    print(ba:getLen());
    print(ba:getAvailable());
    while ba:getAvailable() <= ba:getLen() do 
        scnet.decodeData(ba);
        if ba:getAvailable() == 0 then
            print("aaaaaaaaaaaa");
            break;
        end
    end
end

function scnet.tcpClose(event)
    -- body
    print("socket连接已经关闭!");
end

function scnet.tcpClosed(event)
    -- body
    print("socket连接关闭！");
end


function scnet.tcpConnected(event)
    -- body
    print("socket连接建立成功! ");
end

function scnet.tcpError(event)
    -- body
    print("socket连接出错！");
end

--关闭定时器
function scnet.closeSocket()
    if scnet.socket.isConnected then
        scnet.socket:close();--会接收到SocketTCP.EVENT_CLOSE事件触发scnet.tcpClose()
    end
end

--tcp直接shutdown();
function scnet.onExitSocket()
    scnet.closeSocket();
    scnet.socket:disconnect();--会接收到SocketTCP.EVENT_CLOSED事件触发scnet.tcpClosed()
end



-- 发送数据 msgid 消息id,data 消息数据
function scnet.send(msgid,data)

    --[[
    local _ba = scnet.encodeData(msgid,data);
    print("scnet.send _ba",_ba:getLen());
    if not _ba then 
        print("发送数据出错了.......",msgid);
        return;
    end
    _ba:setPos(1);
    local byteList = {};
    local byteCount = 0;
    -- 取出字节，对字节进行加密
    for i=1,#_ba._buf do
        local tmpBit = string.byte(_ba:readRawByte());
        byteCount = byteCount + tmpBit;
        tmpBit = bit.band(tmpBit + 80,255);
        tmpBit = bit.band(bit.bnot(bit.band(tmpBit,255)),255);
        byteList[i] = tmpBit;
    end
    byteCount = byteCount % 256;
    -- 构造新的字节发送给服务器
    local result = ByteArray.new(ByteArray.ENDIAN_BIG);
    result:writeShort(_ba:getLen() + 3);
    result:writeByte(byteCount);
    for i=1,#byteList do
        result:writeByte(byteList[i]);
    end
    scnet.socket:send(result:getPack());
    --]]

    local result = ByteArray.new(ByteArray.ENDIAN_BIG);
    result:writeShort(_ba:getLen() + 3);
    result:writeByte(byteCount);
    for i=1,#byteList do
        result:writeByte(byteList[i]);
    end
    scnet.socket:send(result:getPack());
end


-- 根据messageid来确定数据格式
function scnet.encodeData(msgid,data)
    if msgid then
        local ba = ByteArray.new(ByteArray.ENDIAN_BIG);
        --local fmt = InfoUtil:getMsgFmt(msgid);
        local fmt = {};
        ba:writeStringUShort("token");   -- 此处为用户token,没有就为""
        for i=1,#fmt do
            scnet.writeData(ba,fmt[i],data);
        end
        local baLength = ba:getLen();
        local bt = ByteArray.new(ByteArray.ENDIAN_BIG);
        bt:writeShort(baLength + 4);         -- 2为message length  2为message type
        bt:writeShort(msgid);
        bt:writeBytes(ba);
        return bt;
    end
end

-- 消息解析
function scnet.decodeData( ba )
--[[
    dump(ba);
    local len = ba:readShort();  -- 读数据总长度
    print("len = %d",len);
    local total = ba:readByte(); -- 一个用于验证的数子
    local byteList = {};
    local tmpTotal = 0;
    for i=1,len - 3 do          -- 去除前两个长度
        local tmpBit = ba:readByte();
        local enByte = scnet.decodeByte(tmpBit);
        tmpTotal = tmpTotal + enByte;
        byteList[i] = enByte;
    end

    local result = ByteArray.new(ByteArray.ENDIAN_BIG);
    for i=1,#byteList do
        result:writeRawByte(string.char(byteList[i]));
    end
    result:setPos(1);
    if (tmpTotal % 256) == total then
        scnet.decodeMsg(result);
    else
        print("scnet.decodeData  total   error");
    end
    -]]
end

-- 根据格式解析数据
function scnet.decodeMsg( byteArray )
    local rData = {};
    local len = byteArray:readShort();
    local msgid = byteArray:readShort();
    local roleString = byteArray:readStringUShort();
    local fmt = InfoUtil:getMsgFmt(msgid);
    for i=1,#fmt do
        scnet.readData(byteArray,fmt[i],rData);
    end
    if rData["result"] ~= 0 then
        print("result  handler is here  ",rData[key]);
        return;
    else
        mgrs.proto:receiveMsg(msgid,rData);
    end
end
-- readData
function scnet.readData( ba,msg_type,data)
    local key = msg_type.key;
    if key then
        data[key] = data[key] or {};
        local _type = msg_type["fmt"];
        if type(_type) == "string" then
            if _type == "string" then
                data[key] = ba:readStringUShort();
            elseif _type == "number" then
                data[key] = ba:readLuaNumber();
            elseif _type == "int" then
                data[key] = ba:readInt();
            elseif _type == "short" then
                data[key] = ba:readShort();
            end
            if key == "result" then         -- 当结果不为零的时候，说明有错误
                if data[key] ~= 0 then
                    print("result  handler is here  ",data[key]);
                    return;
                end
            end

        else
            local _len = ba:readShort(); -- 读取数组长度
            for i=1,_len do
                local tmp = {};
                for j=1,#_type do
                    scnet.readData(ba,_type[j],tmp);
                end
                table.insert(data[key],tmp);
            end
            
        end
    else
        print("找不到对应的 key   scnet.readData",msg_type.key,msg_type,data);
    end
end
-- 数据解密
function scnet.decodeByte( byte )
    local tmp = bit.band(bit.bnot(bit.band(byte,255)),255)
    tmp = bit.band((tmp + 256 - 80),255)
    return tmp
end

return scnet;

--endregion
